home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / fbm12s.lha / flsun.c < prev    next >
C/C++ Source or Header  |  1994-07-18  |  10KB  |  367 lines

  1. /*****************************************************************
  2.  * flsun.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989,1990 by Michael Mauldin.  Permission is granted
  5.  * to use this file in whole or in part for any purpose, educational,
  6.  * recreational or commercial, provided that this copyright notice
  7.  * is retained unchanged.  This software is available to all free of
  8.  * charge by anonymous FTP and in the UUNET archives.
  9.  *
  10.  * flsun.c: 
  11.  *
  12.  * CONTENTS
  13.  *    read_sun (image, rfile, mstr, mlen)
  14.  *    write_sun (image, wfile)
  15.  *
  16.  * EDITLOG
  17.  *    LastEditDate = Mon Jun 25 00:18:04 1990 - Michael Mauldin
  18.  *    LastFileName = /usr2/mlm/src/misc/fbm/flsun.c
  19.  *
  20.  * HISTORY
  21.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  22.  *    Package for Release 1.0
  23.  *
  24.  * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  25.  *    Fixed problem with odd length rows on reading
  26.  *
  27.  * 26-Aug-89  Michael Mauldin (mlm) at Carnegie Mellon University
  28.  *    Beta release (version 0.96) mlm@cs.cmu.edu
  29.  *
  30.  * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  31.  *    Created.
  32.  *****************************************************************/
  33.  
  34. # include <stdio.h>
  35. # include <math.h>
  36. # include <ctype.h>
  37. # include "fbm.h"
  38.  
  39. typedef struct rasterfile {
  40.     long ras_magic;
  41.     long ras_width;
  42.     long ras_height;
  43.     long ras_depth;
  44.     long ras_length;
  45.     long ras_type;
  46.     long ras_maptype;
  47.     long ras_maplength;
  48. } RASHDR;
  49.  
  50. # define RT_STANDARD    1
  51. # define RMT_NONE    0
  52. # define RMT_EQUAL_RGB    1
  53. # define RMT_RAW    2
  54.  
  55. # define RED 0
  56. # define GRN 1
  57. # define BLU 2
  58.  
  59. /****************************************************************
  60.  * write_sun (image, wfile)
  61.  ****************************************************************/
  62.  
  63. #ifndef lint
  64. static char *fbmid =
  65. "$FBM flsun.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
  66. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  67. #endif
  68.  
  69. write_sun (image, wfile)
  70. FBM *image;
  71. FILE *wfile;
  72. { RASHDR rhdr;
  73.   register int i, j, byte;
  74.   register unsigned char *bmp, *rp, *gp, *bp;
  75.   int width, height, plnlen, clrlen, rowlen, depth, bits;
  76.  
  77.   if (image->hdr.planes != 1 && image->hdr.planes != 3)
  78.   { fprintf (stderr,
  79.          "Error, write_sun can only handle images with depth 1 or 3\n");
  80.     return (0);
  81.   }
  82.  
  83.   if (image->hdr.physbits != 8)
  84.   { fprintf (stderr,
  85.          "Error, write_sun can only handle 8 physical bits per pixel\n");
  86.     return (0);
  87.   }
  88.  
  89.   /* This restriction should be fixed */
  90.   if (image->hdr.bits == 1 && (image->hdr.rowlen % 16) != 0)
  91.   { fprintf (stderr,
  92.     "Error, 1 bit deep files must have rowlen (%d) divisible by 16");
  93.     return (0);
  94.   }
  95.  
  96.   /* Allow for input rowlen to be greater than output rowlen */
  97.   if (image->hdr.bits == 1)
  98.   { bits = 1; }
  99.   else
  100.   { bits = 8; }
  101.  
  102. # ifdef DEBUG
  103.   fprintf (stderr,
  104.        "write_sun: [%dx%d] rowlen %d, planes %d, bits %d, physbits %d, using %d\n",
  105.        image->hdr.cols,
  106.        image->hdr.rows,
  107.        image->hdr.rowlen,
  108.        image->hdr.planes,
  109.        image->hdr.bits,
  110.        image->hdr.physbits,
  111.            bits);
  112. # endif
  113.  
  114.   width = image->hdr.cols;
  115.   height = image->hdr.rows;
  116.   rowlen = image->hdr.rowlen;
  117.   plnlen = image->hdr.plnlen;
  118.   clrlen = image->hdr.clrlen;
  119.   depth = bits * image->hdr.planes;
  120.  
  121.   /* Initialize Sun raster header */
  122.   rhdr.ras_magic = SUN_MAGIC;
  123.   rhdr.ras_width = width;
  124.   rhdr.ras_height = height;
  125.   rhdr.ras_depth = depth;
  126.   rhdr.ras_length = plnlen * bits / 8;
  127.   rhdr.ras_type = RT_STANDARD;
  128.   rhdr.ras_maptype = depth > 8 ? RMT_RAW : clrlen ? RMT_EQUAL_RGB : RMT_NONE;
  129.   rhdr.ras_maplength = clrlen;
  130.  
  131.   /* Write rasterfile header - note: use Sun byte order */
  132.   put_long (rhdr.ras_magic, wfile, BIG);
  133.   put_long (rhdr.ras_width, wfile, BIG);
  134.   put_long (rhdr.ras_height, wfile, BIG);
  135.   put_long (rhdr.ras_depth, wfile, BIG);
  136.   put_long (rhdr.ras_length, wfile, BIG);
  137.   put_long (rhdr.ras_type, wfile, BIG);
  138.   put_long (rhdr.ras_maptype, wfile, BIG);
  139.   put_long (rhdr.ras_maplength, wfile, BIG);
  140.   
  141.   /* Dump colormap if need be */
  142.   if (clrlen > 0)
  143.   { fwrite (image->cm, 1, clrlen, wfile); }
  144.   
  145.   /* Write bytes */
  146.   switch (depth)
  147.   { case 32:    
  148.     case 24:    rp = &image->bm[0];
  149.         gp = rp + plnlen;
  150.         bp = gp + plnlen;
  151.  
  152.         for (i=0; i<plnlen; i++)
  153.         { if (depth == 32) fputc (0, wfile);
  154.               fputc (*bp++, wfile);
  155.           fputc (*gp++, wfile);
  156.           fputc (*rp++, wfile);
  157.         }
  158.         break;
  159.  
  160.     case 8:    fwrite (image->bm, 1, plnlen, wfile);
  161.         break;
  162.  
  163.     case 1:    
  164. # ifdef DEBUG
  165.         fprintf (stderr, "Writing Sun 1bit file [%dx%d] rowlen %d\n",
  166.              width, height, rowlen);
  167. # endif
  168.         for (j=0; j<height; j++)
  169.         { bmp = &(image->bm[j*rowlen]);
  170.           byte = 0;
  171.  
  172.           for (i=0; i<rowlen; i++)
  173.           { byte = (byte << 1) | (*bmp++ ? 0 : 1);
  174.  
  175.             if ((i & 7) == 7)
  176.             { fputc (byte, wfile); byte = 0; }
  177.           }
  178.         }
  179.         break;
  180.  
  181.     default:    fprintf  (stderr,
  182.                   "Error, write_sun given invalid depth %d bits\n",
  183.               depth);
  184.         return (0);
  185.   }
  186.   return (1);
  187. }
  188.  
  189. /****************************************************************
  190.  * read_sun (image, rfile)
  191.  ****************************************************************/
  192.  
  193. read_sun (image, rfile, mstr, mlen)
  194. FBM *image;
  195. FILE *rfile;
  196. char *mstr;
  197. int mlen;
  198. { RASHDR rhdr;
  199.   int width, height, plnlen, rowlen, clrlen, res, depth;
  200.   register int i, j, byte;
  201.   register unsigned char *bmp, *rp, *gp, *bp;
  202.   int m1, m2, m3, m4;
  203.  
  204.   m1 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  205.   m2 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  206.   m3 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  207.   m4 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  208.  
  209.   rhdr.ras_magic = (m1 << 24) | (m2 << 16) | (m3 << 8)| (m4);
  210.  
  211.   /* Write rasterfile header - note: use Sun byte order */
  212.   if (rhdr.ras_magic != SUN_MAGIC)
  213.   { fprintf (stderr, "Error, not a Sun raster file (bad magic %08x)\n",
  214.          rhdr.ras_magic);
  215.     return (0);
  216.   }
  217.  
  218.   rhdr.ras_width = get_long (rfile, BIG);
  219.   rhdr.ras_height = get_long (rfile, BIG);
  220.   rhdr.ras_depth = get_long (rfile, BIG);
  221.   rhdr.ras_length = get_long (rfile, BIG);
  222.   rhdr.ras_type = get_long (rfile, BIG);
  223.   rhdr.ras_maptype = get_long (rfile, BIG);
  224.   rhdr.ras_maplength = get_long (rfile, BIG);
  225.  
  226.   /* Check for nonstandard rasterfile formats */
  227.   if (rhdr.ras_type != RT_STANDARD)
  228.   { fprintf (stderr, "Error: rasterfile is not a Sun RT_STANDARD file\n");
  229.     return (0);
  230.   }
  231.  
  232.   if (rhdr.ras_maplength > 0 && rhdr.ras_maptype != RMT_EQUAL_RGB)
  233.   { fprintf (stderr, "Error: color rasterfile is not RMT_EQUAL_RGB\n");
  234.     return (0);
  235.   }
  236.   
  237.   if (rhdr.ras_maplength == 0 &&
  238.       rhdr.ras_maptype != RMT_NONE &&
  239.       rhdr.ras_maptype != RMT_RAW)
  240.   { fprintf (stderr, "Error: black and white rasterfile is not RMT_NONE\n");
  241.     return (0);
  242.   }
  243.  
  244.   if (rhdr.ras_depth != 32 && rhdr.ras_depth != 24 &&
  245.       rhdr.ras_depth != 8 && rhdr.ras_depth != 1)
  246.   { fprintf (stderr, "Error, bits per pixel (%d) must be 1, 8, 24 or 32\n", 
  247.          rhdr.ras_depth);
  248.     return (0);
  249.   }
  250.  
  251.   /* Initialize and allocate input image */  
  252.   width = rhdr.ras_width;
  253.   height = rhdr.ras_height;
  254.   depth = rhdr.ras_depth;
  255.   clrlen = rhdr.ras_maplength;
  256.  
  257.   if (depth == 1)
  258.   { rowlen = 16 * ((width + 15) / 16);
  259.     plnlen = rowlen * height;
  260.   }
  261.   else
  262.   { rowlen = width;
  263.     if (rowlen & 1) rowlen++;
  264.     
  265.     plnlen = rowlen * height; /* Corrected 4-6-90 Gary W. Sherwin */
  266.   }
  267.  
  268.   fprintf (stderr, "Reading Sun raster, [%dx%d], rowlen %d, depth %d, clrlen %d\n",
  269.        width, height, rowlen, depth, clrlen );
  270.   
  271. # ifdef REMOVED
  272.   /* MLM: apparently, DigitalPhoto outputs 24bit w/ colormap */
  273.  
  274.   /* Check for consitency between colormap and depth */
  275.   if (depth > 8 && clrlen > 0)
  276.   { fprintf (stderr,
  277.     "Error, input has colormap of length %d, but %d bits per pixel\n",
  278.     clrlen, depth);
  279.     return (0);
  280.   }
  281. # endif
  282.  
  283.   /* Initialize image header */
  284.   image->hdr.cols = width;
  285.   image->hdr.rows = height;
  286.   image->hdr.planes = (depth >= 24) ? 3 : 1;
  287.   image->hdr.bits = (depth >= 24) ? 8 : depth;
  288.   image->hdr.physbits = 8;
  289.   image->hdr.rowlen = rowlen;
  290.   image->hdr.plnlen = plnlen;
  291.   image->hdr.clrlen = clrlen;
  292.   image->hdr.aspect = 1.0;
  293.   image->hdr.title[0] = '\0';
  294.   image->hdr.credits[0] = '\0';
  295.  
  296.   /* Allocate space */
  297.   alloc_fbm (image);
  298.  
  299.   /* Read colormap if need be */
  300.   if (clrlen > 0 && (res = fread (image->cm, 1, clrlen, rfile)) != clrlen) 
  301.   { fprintf (stderr, "Error: couldn't read colormap, read %d of %d bytes\n",
  302.          res, clrlen);
  303.     return (0);
  304.   }
  305.  
  306.   /* For 24bit image,  discard colormap */
  307.   if (depth == 24 && image->cm)
  308.   { free (image->cm);
  309.     image->hdr.clrlen = clrlen = 0;
  310.   }
  311.  
  312.   /* Read bytes */
  313.   switch (depth)
  314.   { case 32:
  315.     case 24:    rp = &image->bm[0];
  316.         gp = rp + plnlen;
  317.         bp = gp + plnlen;
  318.  
  319.         for (i=0; i<plnlen && !feof (rfile); i++)
  320.         { if (depth == 32) fgetc (rfile); /* Ignore X byte */
  321.           *bp++ = fgetc (rfile);
  322.           *gp++ = fgetc (rfile);
  323.           *rp++ = fgetc (rfile);
  324.         }
  325.         
  326.         if (i<plnlen)
  327.         { fprintf (stderr, "Error: %s %d of %d pixels (%d bytes)\n",
  328.                "EOF on bitmap after",
  329.                i, plnlen, plnlen * image->hdr.planes);
  330.           return (0);
  331.         }
  332.         
  333.         break;
  334.  
  335.     case 8:    if ((res = fread (image->bm, 1, plnlen, rfile)) != plnlen)
  336.         { fprintf (stderr,
  337.                "Error: EOF on bitmap after %d of %d bytes\n",
  338.                res, plnlen);
  339.           return (0);
  340.         }
  341.         break;
  342.  
  343.     case 1:    for (j=0; j<height; j++)
  344.         { bmp = &(image->bm[j * rowlen]);
  345.     
  346.           for (i=0; i<rowlen; i++)
  347.           { if ((i&7) == 0)
  348.             { if ((byte = fgetc (rfile)) == EOF)
  349.               { fprintf (stderr,
  350.                  "Error: EOF on bitmap after %d of %d bytes\n",
  351.                  j*rowlen + i, height*rowlen);
  352.             return (0);
  353.               }
  354.             }
  355.         
  356.             *bmp++ = (byte & 0x80) ? BLACK : WHITE;
  357.             byte <<= 1;
  358.           }
  359.         }
  360.         break;
  361.     default:    fprintf (stderr, "Invalid depth %d bits\n", depth);
  362.         return (0);
  363.   }
  364.  
  365.   return (1);
  366. }
  367.